/*
 * Copyright TLR Team, Inc. All Rights Reserved.
 */
package com.tlr.device.rest;

import com.tfb.rong.Users;
import com.tfb.service.UserAssessmentI;
import com.tfb.service.utility.AppConst;
import static com.tfb.service.utility.AppConst.USER_DB_ID;
import com.tfb.service.utility.HttpUtil;
import com.tfb.service.utility.JsonUtil;
import com.tfb.service.utility.MD5Util;
import com.tfb.service.utility.ShortMessageSender;
import com.tfb.service.utility.Utils;
import com.tfb.service.utility.WechatSign;
import com.tlr.device.model.Result;
import com.tlr.device.service.DeviceDatabaseService;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.Random;
import javax.servlet.ServletContext;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import org.apache.log4j.Logger;
import org.codehaus.jackson.JsonGenerator;
import org.codehaus.jackson.JsonNode;
import org.springframework.context.ApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;

@SuppressWarnings("UseSpecificCatch")
@Path("/user")
public class UserResource {

    private static final Logger log = Logger.getLogger(UserResource.class);
    @Context
    ServletContext context;
    UserAssessmentI userService;
    DeviceDatabaseService deviceService;

    private synchronized void initDatabaseService() {
        if (userService == null) {
            ApplicationContext ac = WebApplicationContextUtils.getWebApplicationContext(context);
            userService = (UserAssessmentI) ac.getBean("userAssessmentService");
            deviceService = (DeviceDatabaseService) ac.getBean("deviceDatabaseService");
        }
    }

    public static String getRandomStringByLength(int length) {
        String base = "abcdefghijklmnopqrstuvwxyz0123456789";
        Random random = new Random();
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < length; i++) {
            int number = random.nextInt(base.length());
            sb.append(base.charAt(number));
        }
        return sb.toString();
    }

    public static String getRandomNumberByLength(int length) {
        String base = "0123456789";
        Random random = new Random();
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < length; i++) {
            int number = random.nextInt(base.length());
            sb.append(base.charAt(number));
        }
        return sb.toString();
    }

    @Path("/unload")
    @GET
    @Produces(MediaType.APPLICATION_JSON)
    public Result<String> unloadDashboard(@Context HttpServletRequest request, @Context HttpServletResponse response) {
        String userID = HttpUtil.getUserDBID(request);
        Cookie cookie = new Cookie(AppConst.USER_DB_ID, userID);
        cookie.setMaxAge(10); //s
        response.addCookie(cookie);
        log.info("unload dashboard page");
        return new Result<>(0, "成功");
    }

    @Path("/logoff")
    @GET
    @Produces(MediaType.APPLICATION_JSON)
    public Result<String> logoffDashboard(@Context HttpServletRequest request, @Context HttpServletResponse response) {
        request.getSession().removeAttribute(USER_DB_ID);
        Cookie cookie = new Cookie(AppConst.USER_DB_ID, "");
        cookie.setMaxAge(0);
        response.addCookie(cookie);
        return new Result<>(0, "成功");
    }

    private boolean validateUserType(Users user) {
        return user.getType() == 2 || user.getType() == 0 || user.getType() == 3;
    }

    @Path("/check_login")
    @GET
    @Produces(MediaType.APPLICATION_JSON)
    public Result<JsonNode> checkDashboardLogin(@Context HttpServletRequest request,
                                                @Context HttpServletResponse response) {
        try {
            String userID = HttpUtil.getUserDBID(request);
            log.info("userID: " + userID);
            if (userID == null) {
                return new Result<>(500, "用户无效或密码错误，请联系管理员");
            }
            initDatabaseService();
            Users user = userService.selectUserByPrimaryKey(userID);
            if (user == null || user.getStatus() != 1 || !validateUserType(user)) {
                return new Result<>(500, "登录的用户无效，请联系管理员");
            }
            JsonUtil jsonU = JsonUtil.createJsonUtility();
            JsonGenerator jsonG = jsonU.getGenerator();
            jsonG.writeStartObject();
            {
                jsonG.writeStringField("user_name", user.getName());
                jsonG.writeStringField("user_token", user.getId());
                jsonG.writeStringField("user_type", Integer.toString(user.getType()));
            }
            jsonG.writeEndObject();
            Cookie cookie = new Cookie(AppConst.USER_DB_ID, userID);
            cookie.setMaxAge(10000000); //300DAYS
            response.addCookie(cookie);
            return new Result<>(0, "成功", JsonUtil.createJson(jsonU.toUTF8String()));
        } catch (Exception e) {
            log.error(Utils.getFullException(e));
            return new Result<>(500, "验证不成功，请联系管理员");
        }
    }

    @Path("/changepwd")
    @POST
    @Produces(MediaType.APPLICATION_JSON)
    public Result<JsonNode> changePassword(@Context HttpServletRequest request,
                                           String message) {
        try {
            initDatabaseService();
            String userID = HttpUtil.getUserDBID(request);
            JsonNode userInfo = JsonUtil.createJson(message);
            String password = userInfo.get("password").asText();
            String newpassword = userInfo.get("newpassword").asText();
            Users user = userService.selectUserByPrimaryKey(userID);
            if (!MD5Util.MD5(password).equals(user.getPassword())) {
                return new Result<>(500, "修改不成功，原始密码不正确");
            }
            user.setPassword(MD5Util.MD5(newpassword));
            userService.updateUser(user);
            return new Result<>(0, "成功");
        } catch (Exception e) {
            log.error(message);
            log.error(Utils.getFullException(e));
            return new Result<>(500, "修改不成功，请联系管理员");
        }
    }

    @Path("/login")
    @POST
    @Produces(MediaType.APPLICATION_JSON)
    public Result<JsonNode> loginDashboard(@Context HttpServletRequest request,
                                           @Context HttpServletResponse response,
                                           String message) {
        try {
            JsonNode loginInfo = JsonUtil.createJson(message);
            String username = loginInfo.has("username") ? loginInfo.get("username").asText() : "";
            String password = loginInfo.has("password") ? loginInfo.get("password").asText() : "";
            initDatabaseService();
            Users user = userService.selectByLogin(username, password);
            if (user == null || user.getStatus() != 1 || !validateUserType(user)) {
                throw new RuntimeException("用户无效： " + username);
            }
            JsonUtil jsonU = JsonUtil.createJsonUtility();
            JsonGenerator jsonG = jsonU.getGenerator();
            jsonG.writeStartObject();
            {
                jsonG.writeStringField("user_token", user.getId());
                jsonG.writeNumberField("user_type", user.getType());
            }
            jsonG.writeEndObject();
            response.addCookie(new Cookie(AppConst.USER_DB_ID, user.getId()));
            request.getSession().setAttribute(AppConst.USER_DB_ID, user.getId());
            return new Result<>(0, "成功", JsonUtil.createJson(jsonU.toUTF8String()));
        } catch (Exception e) {
            log.error(Utils.getFullException(e));
            return new Result<>(500, "用户无效或密码错误，请联系管理员");
        }
    }

    @Path("/wechat_sign")
    @GET
    @Produces(MediaType.APPLICATION_JSON)
    public Result<Map<String, String>> getWechatSign(@QueryParam("url") String url) {
        Map<String, String> sign = WechatSign.sign(AppContext.getTicket(), url);
        if (sign == null)
            return new Result<>(0, "获取签名失败");
        return new Result<>(0, "成功", sign);
    }

    private String checkUserUnique(Users ab) {
        String checkUnique = "";
        if (deviceService.getUserMapper().checkTel(ab.getTel()) > 0) {
            checkUnique += "电话已经被使用";
        }
        if (deviceService.getUserMapper().checkEmail(ab.getEmail()) > 0) {
            if (!checkUnique.isEmpty()) {
                checkUnique += ",";
            }
            checkUnique += "邮箱已经被使用";
        }
        return checkUnique;
    }

    @Path("/register")
    @POST
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.APPLICATION_JSON)
    public Result<String> wechatRegister(@Context HttpServletRequest request, Users user) {
        try {
            initDatabaseService();
            String checkMessage = checkUserUnique(user);
            if (checkMessage != null && !checkMessage.isEmpty()) {
                return new Result<>(500, checkMessage);
            }
            String openID = HttpUtil.getCookieOpenID(request);
            String target = HttpUtil.getCookieTarget(request);
            log.info("Register openid: " + openID);
            JsonNode userBasicInfo = HttpUtil.getUserBasicInfo(openID);
            user.setId(String.format("U%06d", userService.getNextID("user_id")));
            user.setWebchat(openID);
            if (userBasicInfo != null && userBasicInfo.has("headimgurl")) {
                user.setHeader(userBasicInfo.get("headimgurl").asText());
            }
            userService.insertUserInfo(user);
            return new Result<>(0, "成功", target);
        } catch (Exception e) {
            log.error(Utils.getFullException(e));
            return new Result<>(500, "注册失败");
        }
    }

    @Path("/update")
    @POST
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.APPLICATION_JSON)
    public Result<String> updateUser(Users user) {
        try {
            initDatabaseService();
            if (user.getType() == 4) {
                // 4 is urgent contact person, it is only one in TLR DB in current design
                user.setStatus(1);
                List<Users> users = deviceService.getUserMapper().selectAllUserInfoByStatusAndType(user);
                if (!users.isEmpty()) {
                    boolean bFound = false;
                    for (Users u : users) {
                        if (u.getTel().equals(user.getTel())) {
                            bFound = true;
                            break;
                        }
                    }
                    if (!bFound)
                        return new Result<>(500, "天乐融紧急联系员已经存在，不能重复！");
                }
            }
            userService.updateUser(user);
            return new Result<>(0, "成功");
        } catch (Exception e) {
            log.error(Utils.getFullException(e));
            return new Result<>(500, "修改用户信息失败");
        }
    }

    @Path("/del")
    @POST
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.APPLICATION_JSON)
    public Result<String> deleteUser(Users user) {
        try {
            initDatabaseService();
            deviceService.getUserMapper().deleteByPrimaryKey(user.getId());
            return new Result<>(0, "成功");
        } catch (Exception e) {
            log.error(Utils.getFullException(e));
            return new Result<>(500, "删除用户信息失败");
        }
    }

    @Path("/auth_code")
    @GET
    @Produces(MediaType.APPLICATION_JSON)
    public Result<String> getAuthenCode() throws IOException {
        String authCode = getRandomStringByLength(5);
        return new Result<>(0, "成功", authCode);
    }

    @Path("/list")
    @GET
    @Produces(MediaType.APPLICATION_JSON)
    public Result<List<Users>> list(@QueryParam("type") int type) {
        try {
            initDatabaseService();
            Users record = new Users();
            record.setStatus(1);
            record.setType(type);
            List<Users> users = userService.selectAllUserInfoByStatusAndType(record);
            return new Result<>(0, "成功", users);
        } catch (Exception e) {
            log.error(Utils.getFullException(e));
            return new Result<>(500, "读取用户列表失败");
        }
    }

    @Path("/get")
    @GET
    @Produces(MediaType.APPLICATION_JSON)
    public Result<Users> getUser(@Context HttpServletRequest request, @QueryParam("id") String id) {
        try {
            initDatabaseService();
            Users record = new Users();
            if (id == null || id.isEmpty()) {
                Object userDBID = request.getSession().getAttribute(AppConst.USER_DB_ID);
                log.info("session userID: " + String.valueOf(userDBID));
                if (userDBID == null) {
                    userDBID = HttpUtil.getCookieUserDBID(request);
                    log.info("cookie userID: " + String.valueOf(userDBID));
                }
                if (userDBID == null) {
                    return new Result<>(500, "会话过期,读取用户失败");
                }
                id = userDBID.toString();
            }
            record.setId(id);
            Users user = userService.selectBindUserInfo(record);
            return new Result<>(0, "成功", user);
        } catch (Exception e) {
            log.error(Utils.getFullException(e));
            return new Result<>(500, "读取用户失败");
        }
    }

    @Path("/send_verifycode")
    @GET
    @Produces(MediaType.APPLICATION_JSON)
    public Result<String> sendVerifyCode(@QueryParam("mobile") String mobile) {
        try {
            String strCode = getRandomNumberByLength(6);
            String strContent = AppContext.getSmsRegisterTemplate().replaceAll("__@__", strCode);
            String strRsp = ShortMessageSender.batchSend(AppContext.getSmsServerAddress(), AppContext.getSmsUser(),
                                                         AppContext.getSmsPwd(), mobile, strContent, false, "", "");
            if (null != strRsp && strRsp.contains(",0")) {
                return new Result<>(0, "成功", strCode);
            } else {
                return new Result<>(-1, strRsp, null);
            }
        } catch (Exception e) {
            log.error(Utils.getFullException(e));
            return new Result<>(500, "send verify code fail!");
        }
    }

}
